# configure-dhcpd.pm
# Copyright (C) 2006  Stephane Alnet
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
# 

#
# For more information: http://carrierclass.net/
#
use strict; use warnings;

package CCNCore::Provision::Application::dhcpd;
use base qw(CCNCore::Provision::Base);
use CCN::Text;
use CCNCore::Scripting;
use CCN::TimeOffset;

sub anchor_system()
{
    my $self = shift;
    my $dhcpconf = '';
    # Subclass code here
    return $dhcpconf;
}

sub run()
{
    my $self = shift;

    $self->disable('dhcpd'), $self->disable('dhcp'),
    return
        unless $self->p->count("server_network",{server => $self->p->server_pk, dhcp => 'TRUE'}) > 0;

    $self->PACKAGE ('dhcp');
    $self->CHECKFOR ('/etc/init.d/dhcp');
    $self->CHECKFOR ('/usr/sbin/dhcpd');

    my @interfaces = ();
    push @interfaces, 
        $self->sql_get(q(SELECT ifname FROM server_interface WHERE server = ? AND rank = 1),$self->p->server_pk);

    my $interfaces = join(' ',@interfaces);

    CAT '/etc/default/dhcp', <<"EOT";
INTERFACES="$interfaces"
EOT

    $self->enable('dhcpd');
    $self->enable('dhcp');

    my $dhcpconf = <<'EOT';
# ddns-update-style interim; # Bind isn't configured for it, and I don't think we want to support it.
# ignore client-updates;
EOT

    # SQLite can't do IS TRUE
    $self->sql_do_for( <<'SQL', $self->p->server_pk,
        SELECT ipnet_ip,ipnet_mask,router,range_start,range_end,timezone FROM "server_network"
        WHERE server = ? AND dhcp = 'TRUE'
SQL
    sub
    {
        my ($IP,$MASK,$GW,$start,$end,$tz_name) = @_;
        my $NETWORK = "$IP $MASK";

        # Warn but process
        if( not defined $GW )
        {
            $self->warn ("No router defined for network $NETWORK.");
            $GW = '';            
        }
        else
        {
            $GW = qq(option routers             $GW;);
        }
        
        # Do not process
        return $self->error("No IP range defined for network $NETWORK")
            unless defined $start and defined $end;

        # At this time we assume that all networks belong to the same enterprise on a given server
        # (i.e. we don't differentiate between network 192.168.1.0 belonging to enterprise A
        # and network 192.168.1.0 belonging to enterprise B).
        # This is not going to be true for example in multi-tenant units. However what are the limitations
        # in that case?
        # (We can always identify the forwarding agent if we get to need it.)
        # On the other hand, since we map a MAC to a file-server, this should not be too much of a
        # limitation for now.

        our $time_offset = CCN::TimeOffset::time_offset($tz_name);

        my @time_servers = ($self->servername);
        my $TIME_SERVERS = join(' ', map { primary_ip($_) } @time_servers);

        $dhcpconf .= template_text <<"EOT",
subnet _{IP}_ netmask _{MASK}_ {
_{GW}_
option subnet-mask         _{MASK}_;
option domain-name         "_{SYSNAME}_";
option time-offset         _{time_offset}_;
#option time-servers        _{TIME_SERVERS}_;
option ntp-servers         _{TIME_SERVERS}_;
range dynamic-bootp        _{start}_ _{end}_;
default-lease-time         _{DEFAULT_LEASE_TIME}_;
max-lease-time             _{MAX_LEASE_TIME}_;
}
EOT
            {
                IP => $IP, MASK => $MASK,
                GW => $GW,
                SYSNAME => $self$self->p->system_name,
                time_offset => $time_offset,
                TIME_SERVERS => $TIME_SERVERS,
                start => $start,
                end => $end,
                # Default lease time is 10hours (a little bit over a business day)
                DEFAULT_LEASE_TIME => 10 * 3600,
                # Maximum lease time is 12hours
                MAX_LEASE_TIME     => 12 * 3600,
            };


        $dhcpconf .= $self->anchor_system();

    }); # for $NETWORK

    CAT  '/etc/dhcpd.conf', $dhcpconf;
    IF_CHANGED '/etc/dhcpd.conf' => '/etc/init.d/dhcp restart';
}
1;